//////////////////////////////////////////////////
// EASIM project
// easim.win.SynControler
// 6/7/2007 6:39 PM
// Cong Liu
// gzcong@gmail.com

// Copyright (C) 2007
// All rights reserved.
// Refer to LICENSE of JIST (Java In Simulation Time) for terms and conditions of use.

package easim.win;

import easim.net.Node;
import easim.net.Field;

public class SynControler implements jist.runtime.JistAPI.DoNotRewrite
{

  public interface Interactor
  {
    public void interactorAction();
  }

  private static Integer syn;

  public static void start() {
    if (syn != null) {
      throw new RuntimeException("Controler has been started.");
    }
    syn = new Integer(1);
    synchronized (syn) {
      Synchronizer.start();
    }
  }

  public static void interact(Interactor interactor) {
    synchronized (syn) {
      Synchronizer.pause();
      interactor.interactorAction();
      Synchronizer.resume();
    }
  }

  public static Node getNode(int x, int y, int range) {
    synchronized (syn) {
      Synchronizer.pause();
      Node[] nodes = Field.getNeighbors(x, y);
      Node nearest = null;
      double minDist = range;
      for (int i = 0; i < nodes.length; ++ i) {
        double dx = nodes[i].getX() - x;
        double dy = nodes[i].getY() - y;
        double distance = Math.sqrt(dx * dx + dy * dy);
        if (distance <= minDist) {
          minDist = distance;
          nearest = nodes[i];
        }
      }
      Synchronizer.resume();
      return nearest;
    }
  }

  public static void addNode(Node node, int x, int y) {
    synchronized (syn) {
      Synchronizer.pause();
      Field.add(node, x, y);
      Synchronizer.resume();
    }
  }

  public static void moveNode(Node node, int x, int y) {
    synchronized (syn) {
      Synchronizer.pause();
      Field.move(node, x, y);
      Synchronizer.resume();
    }
  }

  public static void deleteNode(Node node) {
    synchronized (syn) {
      Synchronizer.pause();
      Field.delete(node);
      Synchronizer.resume();
    }
  }

  public static Node[] getAllNodes() {
    synchronized (syn) {
      Synchronizer.pause();
      Node[] nodes = Field.getAllNodes();
      Synchronizer.resume();
      return nodes;
    }
  }

  public static void deleteAllNodes() {
    synchronized (syn) {
      Synchronizer.pause();
      Node[] nodes = Field.getAllNodes();
      for (int i = 0; i < nodes.length; ++ i) {
        Field.delete(nodes[i]);
      }
      Synchronizer.resume();
    }
  }

  public static easim.draw.Field getField(int width, int height) {
    synchronized (syn) {
      Synchronizer.pause();
      Node[] nodes = Field.getAllNodes();
      easim.draw.Field field = new easim.draw.Field();
      field.width = width;
      field.height = height;
      for (int i = 0; i < nodes.length; ++ i) {
        easim.draw.Node node = new easim.draw.Node();
        node.x = (int)nodes[i].getX();
        node.y = (int)nodes[i].getY();
        node.size = Frame.NODE_SIZE;
        node.id = "" + nodes[i].getId();
        node.label = node.id;
        node.lineStyle = easim.draw.Setting.LineStyle.SOLID_LINE.toString();
        field.addNode(node);
      }
      for (int i = 0; i < nodes.length; ++ i) {
        Node[] neighbors = Field.getNeighbors(nodes[i].getX(), nodes[i].getY());
        int id1 = nodes[i].getId();
        for (int j = 0; j < neighbors.length; ++ j) {
          int id2 = neighbors[j].getId();
          if (id1 >= id2) continue;
          easim.draw.Link link = new easim.draw.Link();
          link.lineStyle = easim.draw.Setting.LineStyle.SOLID_LINE.toString();
          link.label = "";
          link.arrow = easim.draw.Setting.Arrow.NONE.toString();
          field.addLink(link, "" + id1, "" + id2);
        }
      }
      Synchronizer.resume();
      return field;
    }
  }

}
